package com.cndym.utils;

import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.ByteArrayOutputStream;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.net.URL;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.TimeZone;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.DeflaterOutputStream;
import java.util.zip.InflaterOutputStream;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.ArrayUtils;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.cndym.api.discuz.Base64;
import com.cndym.utils.xml.parse.XmlBean;

public class Utils {
    private static Logger logger = LoggerFactory.getLogger(Utils.class);
    /**
     * 静态常量
     */
    public static final String C_TIME_PATTON_DEFAULT = "yyyy-MM-dd HH:mm:ss";
    public static final String C_DATE_PATTON_DEFAULT = "yyyy-MM-dd";

    public static final int C_ONE_SECOND = 1000;
    public static final int C_ONE_MINUTE = 60 * C_ONE_SECOND;
    public static final long C_ONE_HOUR = 60 * C_ONE_MINUTE;
    public static final long C_ONE_DAY = 24 * C_ONE_HOUR;
    
    public final static String [] NUM_LOTTERY = {"001","113","002","108","109","110","004","106","107","105","010","011","006","009"};
    
    public final static String [] MATCH_LOTTERY = {"200","201"};
    
    public static Integer[] numberArr(String numberCode) {
        if (!isNotEmpty(numberCode)) {
            throw new IllegalArgumentException("参数不能为空");
        }
        String[] arr = numberCode.split(",");
        Integer[] intArr = new Integer[arr.length];
        for (int i = 0; i < arr.length; i++) {
            if (PatternUtils.regValidate(arr[i], "[\\d]+?")) {
                intArr[i] = Integer.parseInt(arr[i]);
            }
        }
        return intArr;
    }

    public static int[] forInstance(int len) {
        int[] temp = new int[len];
        for (int i = 0; i < len; i++) {
            temp[i] = i;
        }
        return temp;
    }

    public static boolean isNotEmpty(String str) {
        return (null != str && "".equals(str.trim()) == false);
    }

    public static boolean isNotEmpty(List list) {
        return (null != list && list.size() > 0);
    }

    public static boolean isNotEmpty(Object str) {
        return (null != str);
    }

    public static boolean isNotEmpty(StringBuffer str) {
        return (null != str && str.length() > 0);
    }

    public static boolean isNotEmptyObject(Object str) {
        return (null != str && !"".equals(str));
    }

    /**
     * 返回一个定长的随机字符串(只包含数字)
     *
     * @param length 随机字符串长度
     * @return 随机字符串
     */
    public static String generateString(int length) {
        StringBuffer sb = new StringBuffer();
        Random random = new Random();
        for (int i = 0; i < length; i++) {
            sb.append(random.nextInt(9));
        }
        return sb.toString();
    }

    /**
     * 生成指定大小的随机数
     *
     * @param num 号码区间
     * @return
     */
    public static int intRandom(int num) {
        Random random = new Random();
        return random.nextInt(num);
    }

    /**
     * 生成0-9的随机数
     *
     * @return
     */
    public static int intRandom() {
        Random random = new Random();
        return random.nextInt(9);
    }

    public static String random(int num) {
        StringBuffer buffer = new StringBuffer();
        for (int i = 0; i < num; i++) {
            buffer.append(intRandom());
        }
        return buffer.toString();
    }
    
    /***
     * 生成数字之间随机数
     */
    public static int intRandom(int minNum, int maxNum) {
        Random random = new Random();
    	return random.nextInt(maxNum)%(maxNum-minNum+1) + minNum;
    }
    
    /**
     * 生成一个 20位的 流水号 yyyyMMddHHmmss + 4 位随机码
     * @return
     */
    public static String getSerialNum(){
    	String serNum = null;
    	
    	SimpleDateFormat simpl =  getSimpleDateFormat("yyyyMMddHHmmss");
    	String dateStr = simpl.format(new Date());
    	serNum = dateStr + random(4);
    	return serNum;
    }

    /**
     * 生成一个 数字和字符的 随机 字符串
     * @param len
     * @return
     */
    public static String getRandomStr(int len) {
		String[] str = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "q",
				"w", "e", "r", "t", "y", "u", "i", "o", "p", "a", "s", "d",
				"f", "g", "h", "j", "k", "l", "z", "x", "c", "v", "b", "n", "m", "Q",
				"W", "E", "R", "T", "Y", "U", "I", "O", "P", "A", "S", "D",
				"F", "G", "H", "J", "K", "L", "Z", "X", "C", "V", "B", "N", "M"  };
		String s = "";
		for (int i = 0; i < len; i++) {
			int a = (int) (Math.random() * 62);
			s += str[a];
		}
		return s;
	}
    
    /**
     * 正则验证
     *
     * @param Content 需要验证的内容
     * @param regex   验证正则表达式
     * @return
     */
    public static boolean regValidate(String Content, String regex) {
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(Content);
        return matcher.matches();
    }

    /**
     * 配置所有
     *
     * @param Content
     * @param regex
     * @return
     */
    public static List<String> regFinds(String Content, String regex) {
        List<String> list = new ArrayList<String>();
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(Content);
        while (matcher.find()) {
            list.add(matcher.group());
        }
        return list;
    }

    /**
     * 正则查找
     *
     * @param Content 查找内容
     * @param regex   匹配正则表达式
     * @return
     */
    public static String regFind(String Content, String regex) {
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(Content);
        matcher.find();
        return matcher.group();
    }

    /**
     * 正则查找
     *
     * @param Content 查找内容
     * @param regex   匹配正则表达式
     * @param index   分组
     * @return
     */
    public static String regFind(String Content, String regex, int index) {
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(Content);
        matcher.find();
        return matcher.group(index);
    }

    /**
     * 正则替换
     *
     * @param Content 查找内容
     * @param regex   匹配正则表达式
     * @return
     */
    public static String regReplace(String Content, String regex, String regStr) {
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(Content);
        return matcher.replaceAll(regStr);
    }

    /**
     * 字符串包含验证,包含验证重复号码
     *
     * @param content 验证内容
     * @param vastr   对比字符串
     * @return
     */
    public static boolean comValidate(String content, String vastr) {
        if (null == content)
            return false;
        if ("".equals(content))
            return false;
        boolean re = true;
        String[] arr = content.split(",");
        int len = arr.length;
        for (int i = 0; i < len; i++) {
            if (vastr.indexOf(arr[i]) < 0) {
                re = false;
                break;
            } else {
                if (vastr.indexOf(arr[i], vastr.indexOf(arr[i]) + 1) > -1) {
                    re = false;
                    break;
                }
            }
        }
        return re;
    }

    /**
     * 字符串包含验证,包含验证重复号码,总位数
     *
     * @param content 验证内容
     * @param vastr   对比字符串
     * @param num     必须满足多少位
     * @return
     */
    public static boolean comValidate(String content, String vastr, int num) {
        if (null == content)
            return false;
        if ("".equals(content))
            return false;
        boolean re = true;
        String[] arr = content.split(",");
        int len = arr.length;
        if (len < num)
            return false;
        for (int i = 0; i < len; i++) {
            if (vastr.indexOf(arr[i]) < 0) {
                re = false;
                break;
            } else {
                if (vastr.indexOf(arr[i], vastr.indexOf(arr[i]) + 1) > -1) {
                    re = false;
                    break;
                }
            }
        }
        return re;
    }

    /**
     * 中文
     *
     * @return
     */
    public static String encodStr(String str) {
        try {
            return new String(str.getBytes("iso-8859-1"), "utf-8");
        } catch (Exception e) {
            return str;
        }
    }

    /**
     * 中文
     *
     * @return
     */
    public static String encodStr(String str, String encoding) {
        try {
            return new String(str.getBytes("iso-8859-1"), encoding);
        } catch (Exception e) {
            return str;
        }
    }

    /**
     * 格式化日期
     *
     * @return
     */
    public static Date formatDate(String date) {
        return formatDate(date, "yyyy-MM-dd HH:mm:ss");
    }

    /**
     * 格式化日期
     *
     * @return
     */
    public static Date formatDate(String date, String style) {
        date = formatStr(date);
        if (null == date) {
            return null;
        }
        SimpleDateFormat simpleDateormat = new SimpleDateFormat(style);
        try {
            return simpleDateormat.parse(date);
        } catch (ParseException e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 转换指定时间为指定格式
     *
     * @param date
     * @param format
     * @return
     */
    public static String formatDate2Str(Date date, String format) {
        if (date == null) {
            return null;
        }

        if (format == null || format.equals("")) {
            format = C_TIME_PATTON_DEFAULT;
        }
        SimpleDateFormat sdf = getSimpleDateFormat(format);
        return sdf.format(date);
    }

    /**
     * 拿到指定输出格式的SimpleDateFormat
     *
     * @param format
     * @return
     */
    public static SimpleDateFormat getSimpleDateFormat(String format) {
        SimpleDateFormat sdf;
        if (format == null) {
            sdf = new SimpleDateFormat(C_TIME_PATTON_DEFAULT);
        } else {
            sdf = new SimpleDateFormat(format);
        }

        return sdf;
    }

    /**
     * 得到当前日期
     *
     * @return
     */
    public static String today() {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return simpleDateFormat.format(new Date());
    }

    /**
     * 根据格式得到当前日期
     *
     * @param format
     * @return
     */

    public static String today(String format) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(format);
        return simpleDateFormat.format(new Date());
    }

    /**
     * 得到昨天的日期yyyy-MM-dd
     *
     * @return
     */
    public static String yesterday() {
        Date date = new Date();
        date.setTime(date.getTime() - 86400000);
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        return simpleDateFormat.format(date);
    }

    /**
     * 得到昨天的日期yyyy-MM-dd
     *
     * @return
     */
    public static String yesterday(String style) {
        Date date = new Date();
        date.setTime(date.getTime() - 86400000);
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(style);
        return simpleDateFormat.format(date);
    }

    /**
     * 得到明天的日期yyyy-MM-dd
     *
     * @return
     */
    public static String tomorrow() {
        Date date = new Date();
        date.setTime(date.getTime() + 86400000);
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        return simpleDateFormat.format(date);
    }

    /**
     * 得到前天的日期yyyy-MM-dd
     */
    public static String beforeYesterday() {
        Date date = new Date();
        date.setTime(date.getTime() - 2 * 86400000);
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        return simpleDateFormat.format(date);
    }

    /**
     * 得到后天的日期yyyy-MM-dd
     */
    public static String afterTomorow() {
        Date date = new Date();
        date.setTime(date.getTime() + 2 * 86400000);
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        return simpleDateFormat.format(date);
    }

    /**
     * 得到今天的星期
     *
     * @return 今天的星期
     */
    public static String getWeek() {
        SimpleDateFormat sdf = new SimpleDateFormat("E");
        return sdf.format(new Date());
    }

    public static String getWeekByDate(String dateStr, String style) {
        Date date = Utils.formatDate(dateStr, style);
        SimpleDateFormat sdf = new SimpleDateFormat("E");
        return sdf.format(date);
    }

    /**
     * 获得本周一的日期
     *
     * @return
     */
    public static Date getMondayOFWeek() {
        int mondayPlus = getMondayPlus();
        Calendar currentDate = Calendar.getInstance();
        currentDate.add(Calendar.DATE, mondayPlus);
        currentDate.set(Calendar.HOUR, 0);
        currentDate.set(Calendar.MINUTE, 0);
        currentDate.set(Calendar.SECOND, 0);
        Date monday = currentDate.getTime();
        return monday;
    }

    /**
     * 获得本周星期日的日期
     *
     * @return
     */
    public static Date getCurrentWeekday() {
        int mondayPlus = getMondayPlus();
        Calendar currentDate = Calendar.getInstance();
        currentDate.add(Calendar.DATE, mondayPlus + 6);
        currentDate.set(Calendar.HOUR, 23);
        currentDate.set(Calendar.MINUTE, 59);
        currentDate.set(Calendar.SECOND, 59);
        Date monday = currentDate.getTime();
        return monday;
    }

    /**
     * 获得当前日期与本周日相差的天数
     *
     * @return
     */
    private static int getMondayPlus() {
        Calendar cd = Calendar.getInstance();
        // 获得今天是一周的第几天，星期日是第一天，星期二是第二天......
        int dayOfWeek = cd.get(Calendar.DAY_OF_WEEK) - 1; // 因为按中国礼拜一作为第一天所以这里减1
        if (dayOfWeek == 1) {
            return 0;
        } else {
            return 1 - dayOfWeek;
        }
    }

    /**
     * 根据日期获取周几
     *
     * @param date
     * @return
     */

    public static String getWeekByDate(Date date) {
        SimpleDateFormat sdf = new SimpleDateFormat("E");
        return sdf.format(date);
    }

    public static Date getLastDayOfMonth(Date date) {
        String str = "";
        Calendar lastDate = Calendar.getInstance();
        lastDate.setTime(date);
        lastDate.set(Calendar.DATE, 1);// 设为当前月的1号
        lastDate.add(Calendar.MONTH, 1);// 加一个月，变为下月的1号
        lastDate.add(Calendar.DATE, -1);// 减去一天，变为当月最后一天
        lastDate.set(Calendar.HOUR_OF_DAY, 23);
        lastDate.set(Calendar.MINUTE, 59);
        lastDate.set(Calendar.SECOND, 59);
        return lastDate.getTime();
    }

    public static Date getFirstDayOfMonth(Date date) {
        String str = "";
        Calendar firstDate = Calendar.getInstance();
        firstDate.setTime(date);
        firstDate.set(Calendar.DATE, 1);// 设为当前月的1号
        firstDate.set(Calendar.HOUR_OF_DAY, 0);
        firstDate.set(Calendar.MINUTE, 0);
        firstDate.set(Calendar.SECOND, 0);
        return firstDate.getTime();
    }

    /**
     * 日期的指定域加减
     *
     * @param time  时间戳(长整形字符串)
     * @param field 加减的域,如date表示对天进行操作,month表示对月进行操作,其它表示对年进行操作
     * @param num   加减的数值
     * @return 操作后的时间戳(长整形字符串)
     */
    public static String addDate(String time, String field, int num) {
        int fieldNum = Calendar.YEAR;
        if (field.equals("m")) {
            fieldNum = Calendar.MONTH;
        }
        if (field.equals("d")) {
            fieldNum = Calendar.DATE;
        }
        Calendar cal = Calendar.getInstance();
        cal.setTimeInMillis(Long.parseLong(time));
        cal.add(fieldNum, num);
        return String.valueOf(cal.getTimeInMillis());
    }

    /**
     * 日期的指定域加减
     *
     * @param date  时间戳(长整形字符串)
     * @param field 加减的域,如date表示对天进行操作,month表示对月进行操作,其它表示对年进行操作
     * @param num   加减的数值
     * @return 操作后的时间戳(长整形字符串)
     */
    public static Date addDate(Date date, String field, int num) {
        if (date != null) {
            int fieldNum = Calendar.YEAR;
            if (field.equals("m")) {
                fieldNum = Calendar.MONTH;
            }
            if (field.equals("d")) {
                fieldNum = Calendar.DATE;
            }
            if(field.equals("f")){
            	fieldNum = Calendar.MINUTE;
            }
            if(field.equals("h")){
            	fieldNum = Calendar.HOUR_OF_DAY;
            }
            if(field.equals("mi")){
         	   fieldNum = Calendar.MINUTE; 
            }
            Calendar cal = Calendar.getInstance();
            cal.setTimeInMillis(date.getTime());
            cal.add(fieldNum, num);
            return new Date(cal.getTimeInMillis());
        }
        return null;
    }
    
    
   
    /**
     * 日期的指定域加减
     *
     * @param field 加减的域,如date表示对天进行操作,month表示对月进行操作,其它表示对年进行操作
     * @param num   加减的数值
     * @return 操作后的时间戳(长整形字符串)
     */
    public static long addDate(String field, int num) {
        field = field.toLowerCase();
        int fieldNum = Calendar.YEAR;
        if (field.equals("m")) {
            fieldNum = Calendar.MONTH;
        }
        if (field.equals("d")) {
            fieldNum = Calendar.DATE;
        }
        Calendar cal = Calendar.getInstance();
        cal.setTimeInMillis(new Date().getTime());
        cal.add(fieldNum, num);

        return cal.getTimeInMillis();
    }

    /**
     * 得到一个日期是否是上午
     *
     * @param date 日期
     * @return 日期为上午时返回true
     */
    public static boolean isAm(Date date) {
        boolean flag = false;
        SimpleDateFormat sdf = new SimpleDateFormat("H");
        if (sdf.format(date).compareTo("12") < 0) {
            flag = true;
        }
        return flag;
    }

    public static Long getMinuteByDate(Date date1, Date date2) {
        try {
            Long num2 = date2.getTime();
            Long num1 = date1.getTime();
            if (num2 > num1) {
                return num2 - num1;
            } else {
                return 0L;
            }
        } catch (Exception e) {
            return 0L;
        }

    }

    /**
     * lfx 下面函数使用
     */
    private static Map<String, Integer> weekMap;
    private static Map<Integer, String> weekChinaMap;

    static {
        weekMap = new HashMap<String, Integer>();
        weekMap.put("周六", 0);
        weekMap.put("周日", 1);
        weekMap.put("周一", 2);
        weekMap.put("周二", 3);
        weekMap.put("周三", 4);
        weekMap.put("周四", 5);
        weekMap.put("周五", 6);

        weekChinaMap = new HashMap<Integer, String>();

        weekChinaMap.put(7, "星期六");
        weekChinaMap.put(1, "星期日");
        weekChinaMap.put(2, "星期一");
        weekChinaMap.put(3, "星期二");
        weekChinaMap.put(4, "星期三");
        weekChinaMap.put(5, "星期四");
        weekChinaMap.put(6, "星期五");
    }

    /**
     * 获取今天以后的最近的星期weekDay那天的日期 lfx
     *
     * @param weekDay 上面weekMap里面的key
     * @return 日期yyyyMMdd
     */
    public static String getDateOfNextWeekDay(String weekDay) {
        Calendar c = Calendar.getInstance();
        int offDay = weekMap.get(weekDay) - c.get(Calendar.DAY_OF_WEEK);
        c.add(Calendar.DAY_OF_YEAR, offDay < 0 ? 7 + offDay : offDay);
        String dateStr = DateUtils.formatDate2Str(c.getTime(), "yyyyMMdd");
        return dateStr;
    }

    /**
     * IP转换成10位数字
     *
     * @param ip IP
     * @return 10位数字
     */
    public static long ip2num(String ip) {
        long ipNum = 0;
        try {
            if (ip != null) {
                String ips[] = ip.split("\\.");
                for (int i = 0; i < ips.length; i++) {
                    int k = Integer.parseInt(ips[i]);
                    ipNum = ipNum + k * (1L << ((3 - i) * 8));
                }
            }
        } catch (Exception e) {
        }
        return ipNum;
    }

    /**
     * 将十进制整数形式转换成127.0.0.1形式的ip地址
     */
    public static String num2ip(long longIp) {
        StringBuffer sb = new StringBuffer("");
        // 直接右移24位
        sb.append(String.valueOf((longIp >>> 24)));
        sb.append(".");
        // 将高8位置0，然后右移16位
        sb.append(String.valueOf((longIp & 0x00FFFFFF) >>> 16));
        sb.append(".");
        // 将高16位置0，然后右移8位
        sb.append(String.valueOf((longIp & 0x0000FFFF) >>> 8));
        sb.append(".");
        // 将高24位置0
        sb.append(String.valueOf((longIp & 0x000000FF)));
        return sb.toString();
    }

    /**
     * 判断是否为整数
     *
     * @param str 传入的字符串
     * @return 是整数返回true, 否则返回false
     */
    public static boolean isInt(String str) {
        if (null == str)
            return false;
        str = str.trim();
        Pattern pattern = Pattern.compile("^[-\\+]?[\\d]*$");
        return pattern.matcher(str).matches();
    }

    /**
     * 判断是否为整数
     *
     * @param str 传入的字符串
     * @return 是整数返回true, 否则返回false
     */
    public static int formatInt(String str, int def) {
        try {
            return Integer.parseInt(str);
        } catch (Exception e) {
            return def;
        }
    }

    /**
     * 判断是否为整数
     *
     * @param str 传入的字符串
     * @return 是整数返回true, 否则返回false
     */
    public static long formatLong(String str, int def) {
        try {
            return Long.parseLong(str);
        } catch (Exception e) {
            return def;
        }
    }

    /**
     * 判断是否为整数
     *
     * @param str 传入的字符串
     * @return 是整数返回true, 否则返回false
     */
    public static long formatLong(Long str, int def) {
        if (isNotEmpty(str)) {
            return str;
        } else {
            return def;
        }
    }

    /**
     * 判断是否为整数
     *
     * @param str 传入的字符串
     * @return 是整数返回true, 否则返回false
     */
    public static Long formatLong(String str) {
        try {
            return Long.parseLong(str);
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * 判断是否为整数
     *
     * @param str 传入的字符串
     * @return 是整数返回true, 否则返回false
     */
    public static Integer formatInt(String str, Integer def) {
        try {
            return Integer.parseInt(str);
        } catch (Exception e) {
            return def;
        }
    }

    /**
     * 转换字符串为浮点数
     *
     * @param str 待格式化字符串
     * @param def 默认值
     * @return
     */
    public static Float Double(String str, Float def) {
        try {
            return Float.parseFloat(str);
        } catch (Exception e) {
            return def;
        }
    }

    /**
     * 转换字符串为浮点数
     *
     * @param str 待格式化字符串
     * @param def 默认值
     * @return
     */
    public static Double formatDouble(String str, Double def) {
        try {
            return Double.parseDouble(str);
        } catch (Exception e) {
            return def;
        }
    }

    /**
     * 转换BigDecimal为浮点数
     *
     * @param obj 待格式化字符串
     * @return
     */
    public static Double formatDouble(Object obj) {
        Double num = 0d;
        try {
            if (isNotEmpty(obj)) {
                BigDecimal db = (BigDecimal) obj;
                num = db.doubleValue();
            }
            return num;
        } catch (Exception e) {
        	e.printStackTrace();
            return num;
        }
    }

    public static String formatDouble(Double value, String pattern) {
        if (pattern == null) {
            pattern = "#.##";
        }
        DecimalFormat df = new DecimalFormat(pattern);
        return df.format(value);
    }

    /**
     * 转换字符串为浮点数
     *
     * @param str 待格式化字符串
     * @param def 默认值
     * @return
     */
    public static Double formatDouble(Double str, Double def) {
        if (isNotEmpty(str)) {
            return str;
        }
        return def;
    }

    /**
     * 判断是否为浮点数，包括double和float
     *
     * @param str 传入的字符串
     * @return 是浮点数返回true, 否则返回false
     */
    public static boolean isDouble(String str) {
        if (null == str)
            return false;
        Pattern pattern = Pattern.compile("^[-\\+]?[.\\d]*$");
        return pattern.matcher(str).matches();
    }

    /**
     * 判断输入的字符串是否符合Email样式.
     *
     * @param str 传入的字符串
     * @return 是Email样式返回true, 否则返回false
     */
    public static boolean isEmail(String str) {
        if (null == str)
            return false;
        Pattern pattern = Pattern.compile("^\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*$");
        return pattern.matcher(str).matches();
    }

    /**
     * 判断输入的字符串是否为纯汉字
     *
     * @param str 传入的字符串
     * @return 如果是纯汉字返回true, 否则返回false
     */
    public static boolean isChinese(String str) {
        if (null == str)
            return false;
        Pattern pattern = Pattern.compile("[\u0391-\uFFE5]+$");
        return pattern.matcher(str).matches();
    }

    /**
     * 是否为空白,包括null和""
     *
     * @param str
     * @return
     */
    public static boolean isEmpty(String str) {
        return str == null || str.trim().length() == 0;
    }

    /**
     * 是否为空白,包括null和""
     *
     * @param str
     * @return
     */
    public static boolean isEmpty(List str) {
        return str == null || str.size() == 0;
    }

    /**
     * 奖字符转成16进制
     *
     * @return
     */
    public static String toHexString(String s) {
        String str = "";
        for (int i = 0; i < s.length(); i++) {
            int ch = (int) s.charAt(i);
            String s4 = "0000" + Integer.toHexString(ch);
            str = str + s4.substring(s4.length() - 4) + " ";
        }
        return str;
    }

    /**
     * 人民币转成大写
     *
     * @param value
     * @return String
     */
    public static String hangeToBig(double value) {
        char[] hunit = {'拾', '佰', '仟'}; // 段内位置表示
        char[] vunit = {'万', '亿'}; // 段名表示
        char[] digit = {'零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖'}; // 数字表示
        long midVal = (long) (value * 100); // 转化成整形
        String valStr = String.valueOf(midVal); // 转化成字符串

        String head = valStr.substring(0, valStr.length() - 2); // 取整数部分
        String rail = valStr.substring(valStr.length() - 2); // 取小数部分

        String prefix = ""; // 整数部分转化的结果
        String suffix = ""; // 小数部分转化的结果
        // 处理小数点后面的数
        if (rail.equals("00")) { // 如果小数部分为0
            suffix = "整";
        } else {
            suffix = digit[rail.charAt(0) - '0'] + "角" + digit[rail.charAt(1) - '0'] + "分"; // 否则把角分转化出来
        }
        // 处理小数点前面的数
        char[] chDig = head.toCharArray(); // 把整数部分转化成字符数组
        char zero = '0'; // 标志'0'表示出现过0
        byte zeroSerNum = 0; // 连续出现0的次数
        for (int i = 0; i < chDig.length; i++) { // 循环处理每个数字
            int idx = (chDig.length - i - 1) % 4; // 取段内位置
            int vidx = (chDig.length - i - 1) / 4; // 取段位置
            if (chDig[i] == '0') { // 如果当前字符是0
                zeroSerNum++; // 连续0次数递增
                if (zero == '0') { // 标志
                    zero = digit[0];
                } else if (idx == 0 && vidx > 0 && zeroSerNum < 4) {
                    prefix += vunit[vidx - 1];
                    zero = '0';
                }
                continue;
            }
            zeroSerNum = 0; // 连续0次数清零
            if (zero != '0') { // 如果标志不为0,则加上,例如万,亿什么的
                prefix += zero;
                zero = '0';
            }
            prefix += digit[chDig[i] - '0']; // 转化该数字表示
            if (idx > 0)
                prefix += hunit[idx - 1];
            if (idx == 0 && vidx > 0) {
                prefix += vunit[vidx - 1]; // 段结束位置应该加上段名如万,亿
            }
        }

        if (prefix.length() > 0)
            prefix += '圆'; // 如果整数部分存在,则有圆的字样
        return prefix + suffix; // 返回正确表示
    }

    /**
     * 在字符串头部添加字符，使原字符串达到指定的长度
     *
     * @param source  源字符串
     * @param filling 填充字符
     * @param lastLen 填充后的总长度
     * @return 如果源字符串长度大于lastLen，返回原字符串，否则用filling填充源字符串后返回结果
     */
    public static String fillString(String source, char filling, int lastLen) {
        StringBuffer temp = new StringBuffer();
        if (source.length() < lastLen) {
            int fillLen = lastLen - source.length();
            for (int i = 0; i < fillLen; i++) {
                temp.append(filling);
            }
        }
        temp.append(source);
        return temp.toString();
    }

    /**
     * 格式化一个数字字符串为9，999，999.99的格式,如果字符串无法格式化返回0.00
     *
     * @param money 数字字符串
     * @return 格式化好的数字字符串
     */
    public static String formatMoney(String money) {
        String formatMoney = "0.00";
        try {
            DecimalFormat myformat3 = new DecimalFormat();
            myformat3.applyPattern(",##0.00");
            double n = Double.parseDouble(money);
            formatMoney = myformat3.format(n);
        } catch (Exception ex) {
        }
        return formatMoney;
    }

    /**
     * 格式化一个数字字符串为9，999，999.99的格式,如果字符串无法格式化返回0.00
     *
     * @param money 数字字符串
     * @return 格式化好的数字字符串
     */
    public static String formatMoney(double money) {
        String formatMoney = "0.00";
        try {
            DecimalFormat myformat3 = new DecimalFormat();
            myformat3.applyPattern(",##0.00");
            formatMoney = myformat3.format(money);
        } catch (Exception ex) {
        }
        return formatMoney;
    }

    /**
     * 从右边截取指定长度的字符串
     *
     * @param src 源字符串
     * @param len 长度
     * @return 截取后的字符串
     */
    public static String right(String src, int len) {
        String dest = src;
        if (src != null) {
            if (src.length() > len) {
                dest = src.substring(src.length() - len);
            }
        }

        return dest;
    }

    /**
     * 得到以&分割的字符数组
     *
     * @param str
     * @return
     */
    public static String[] strToArr(String str, int num) {
        if (null == str || "".equals(str))
            return null;
        String[] arr = str.split("&");
        int len = arr.length;
        if (len != num)
            return null;
        return arr;
    }

    /**
     * 得到以&分割的字符数组
     *
     * @param str
     * @return
     */
    public static String[] strToArr(String str) {
        if (null == str || "".equals(str))
            return null;
        String[] arr = str.split("&");
        return arr;
    }

    /**
     * 得到以pix规定的符号分割的数组
     *
     * @param str
     * @param pix
     * @return
     */
    public static String[] strToArr(String str, String pix) {
        if (null == str || "".equals(str))
            return null;
        return str.split(pix);
    }

    /**
     * 去除号码两边的空格
     *
     * @param para    原字符串
     * @param defalut 如果为空默认值
     * @return
     */
    public static String formatStr(String para, String defalut) {
        if (null != para) {
            para = para.trim();
            if ("".equals(para)) {
                return defalut;
            }
            return para;
        } else {
            return defalut;
        }
    }

    /**
     * 去除号码两边的空格
     *
     * @param para 原字符串
     * @return
     */
    public static String formatStr(String para) {
        if (null != para) {
            para = para.trim();
            if ("".equals(para)) {
                return null;
            }
            return para;
        } else {
            return null;
        }
    }

    public static String fullByZero(int in, int len) {
        String str = Integer.toString(in);
        if (null != str) {
            while (str.length() < len) {
                str = "0" + str;
            }
        }
        return str;
    }

    public static String fullByZero(String str, int len) {
        if (null != str) {
            while (str.length() < len) {
                str = "0" + str;
            }
        }
        return str;
    }

    public static String formatNumber(double amount) {
        DecimalFormat decimalFormat = new DecimalFormat("#");
        String temp = decimalFormat.format(amount);
        return temp;
    }

    public static String formatNumberZ(double amount) {
        DecimalFormat decimalFormat = new DecimalFormat("#0.00");
        String temp = decimalFormat.format(amount);
        return temp;
    }

    public static String formatNumberEx(double amount) {
        DecimalFormat decimalFormat = new DecimalFormat("#");
        String temp = decimalFormat.format(amount);
        if (temp.indexOf(".") == 0) {
            return "0%";
        }
        return temp + "%";
    }

    /**
     * 本方法用dom4j解析xml
     *
     * @param xmlStr (xml内容的字符串)
     * @param key
     * @return boolean
     */
    public static boolean encryptMsg(String xmlStr, String key) {
        Document doc = null;
        StringBuilder sb = new StringBuilder(64);
        String timeTag = "", digest = "", body = "", finalStr = "";
        try {
            doc = DocumentHelper.parseText(xmlStr);
            Element root = doc.getRootElement();
            /**
             * 1,先得到timeTag的值 2,再得到digest的值 3,最后得到body（包含）里的所以节点 4,拼接timeTag+key+body得到最终值 5,加密拼接后的字符串 6,把加密后的字符串和digest比较,相等返回true，否则false
             */
            timeTag = root.element("header").elementText("timeTag");
            digest = root.element("header").elementText("digest");
            body = xmlStr.substring(xmlStr.indexOf("<body"), xmlStr.indexOf("</message>"));
            finalStr = sb.append(timeTag).append(key).append(body).toString();
            // 加密
            String bytes = Md5.Md5(finalStr);

            return digest.equals(bytes);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    public static String getClassPath() {
        URL url = Utils.class.getClassLoader().getResource("");
        if (null == url) {
            return "";
        }
        return url.getPath();
    }

    public static String getIpAddress(javax.servlet.http.HttpServletRequest request) {
        String ip = request.getHeader("x-forwarded-for");
        String localIP = "127.0.0.1";
        if ((ip == null) || (ip.length() == 0) || (ip.equalsIgnoreCase(localIP)) || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("http_x_forwarded_for");
        }
        if ((ip == null) || (ip.length() == 0) || (ip.equalsIgnoreCase(localIP)) || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if ((ip == null) || (ip.length() == 0) || (ip.equalsIgnoreCase(localIP)) || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if ((ip == null) || (ip.length() == 0) || (ip.equalsIgnoreCase(localIP)) || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        if (ip.contains(",")) {
            return ip.split(",")[0].trim();
        } else {
            return ip;
        }
    }

    public static String getMid(String sid) {
        return sid + today("yyyyMMddHHmmssSSS");
    }

    public static int passWordStrength(String password) {
        // 0:低，1：中，2高
        if (PatternUtils.regValidate(password, ".*[A-Za-z0-9]+.*") && PatternUtils.regValidate(password, ".*[\\W]+")) {
            return 2;
        }
        if (PatternUtils.regValidate(password, ".*[A-Za-z]+.*") && PatternUtils.regValidate(password, ".*[0-9]+.*")) {
            return 1;
        }
        if (PatternUtils.regValidate(password, "[0-9]+")) {
            return 0;
        }
        if (PatternUtils.regValidate(password, "[A-Za-z]+")) {
            return 0;
        }
        return -1;
    }

    public static Map<String, Integer> getPageStartAndEnd(int page, int pageTotal) {
        if (pageTotal <= 0) {
            pageTotal = 1;
        }
        Map<String, Integer> result = new HashMap<String, Integer>();
        int start = 0;
        int end = 0;

        if (pageTotal > 5) {
            if (page - 2 > 0) {
                start = page - 2;
                if (page + 2 <= pageTotal) {
                    end = page + 2;
                } else {
                    start = pageTotal - 5;
                    end = pageTotal;
                }
            } else {
                start = 1;
                end = 5;
            }
        } else {
            start = 1;
            end = pageTotal;
        }

        result.put("start", start);
        result.put("end", end);
        return result;
    }

    public static String getCookieValue(Cookie[] cookies, String cookieName, String defaultValue) {
        if (!Utils.isNotEmpty(cookies)) {
            return defaultValue;
        }
        for (int i = 0; i < cookies.length; i++) {
            Cookie cookie = cookies[i];
            if (cookieName.equals(cookie.getName()))
                return (cookie.getValue());
        }
        return (defaultValue);
    }

    public static String reNull(String str) {
        if (null == str) {
            return "0";
        }
        return str;
    }

    public static void deleteCookie(HttpServletResponse response) {
        // 删除cookie
        Cookie coo = new Cookie("code", "");
        coo.setMaxAge(0);
        coo.setPath("/"); // 路径
        coo.setDomain("localhost");// 域名
        response.addCookie(coo); // 在本地硬盘上产生文件
    }

    public static String getEmailDomain(String email) {
        if (Utils.isEmpty(email)) {
            return "";
        }
        if (!Utils.isEmail(email)) {
            return "";
        }
        String[] mailArray = email.split("@");
        if (mailArray.length != 2) {
            return "";
        }
        if (mailArray[1].equals("gmail.com")) {
            return "http://www.gmail.com";
        }

        return "http://mail." + mailArray[1];
    }

    public static String getVerifyCode(int len) {
        StringBuffer temp = new StringBuffer();
        String arr = "abcdefghijklmnopkrstuvwxyzABCDEFGHIJKLMNOPKRSTUVWXYZ0123456789";
        String[] array = arr.split("");
        while (temp.length() < len) {
            int random = Utils.intRandom(62);
            if (Utils.isNotEmpty(array[random])) {
                temp.append(array[random]);
            }
        }
        return temp.toString();
    }

    public static String objectToString(Object obj) {
        if (isNotEmpty(obj)) {
            return obj.toString();
        }
        return "";
    }

    /**
     * 根据指定的符号，截取掉符号之后几位数据
     *
     * @param num 要截取的数据
     * @param len 截取之后符号后面所剩个数
     * @param tag 截取的符号
     * @return
     */
    public static String objectSubString(Object num, int len, String tag) {
        if (isNotEmpty(num)) {
            String n = num.toString();
            int index = n.indexOf(tag);
            if (index > 0) {
                int j = n.length() - index;
                n = n.substring(0, j > len ? index + len + 1 : n.length());
                if (j <= len) {
                    for (int i = 0; i < j - 1; i++) {
                        n = n + "0";
                    }
                }
            }
            return n;
        }
        return "";
    }

    public static boolean validateCode(String idCode) {
        String code = idCode.trim();
        return IdCardUtils.validateCard(code);
    }

    public static boolean validateEmail(String email) {
        return Utils.regValidate(email, "^\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*$");
    }

    public static boolean validateMobile(String mobile) {
        return Utils.regValidate(mobile, "^1{1}[3|5|8]{1}\\d{9}$");
    }

    public static String formatMobile(String mobile) {
        if (Utils.isNotEmpty(mobile)) {
            if (mobile.length() == 11) {
                mobile = mobile.substring(0, 3) + "****" + mobile.substring(7, mobile.length());
            }
        }        
        return mobile;
    }
    
    //联合登录部分，屏蔽部分特殊字符，替换前缀&去掉邮箱后半截
    public static String formatUserName(String userName) {
        if (Utils.isNotEmpty(userName)) {
            if (userName.startsWith("kql_") || userName.startsWith("ganjI_") || userName.startsWith("etk_")
                    || userName.startsWith("yyYuY_")) {
                if(userName.indexOf("@") >-1)
                    userName = userName.substring(0, userName.indexOf("@"));
            }
            userName = userName.replaceFirst("kql_", "看球啦-")
                    .replaceFirst("ganjI_", "赶集网-").replaceFirst("yyYuY_", "YY语音平台-")
                    .replaceFirst("etk_", "易淘客-");
        }
        return userName;
    }
    
    public static String formatUserNickName(String nickName) {
        if (Utils.validateMobile(nickName)) {
            nickName = Utils.formatMobile(nickName);
        }else{
            nickName = Utils.formatUserName(nickName);
        }
        if(nickName!= null && (nickName.startsWith("ZFB_") || nickName.startsWith("QQ_"))){
            nickName = nickName.length()>14 ? (nickName.substring(0, 14) + "...") : nickName;
        }
        return nickName;
    }
    
    /**
     * 屏蔽部分特殊规则的用户名2
     * @param userName
     * @return
     */
    public static String formatUserName2(String userName) {
        if (Utils.isNotEmpty(userName)) {
            StringBuilder sb = null;
            if (userName.startsWith("kql_") || userName.startsWith("ganjI_") || userName.startsWith("etk_")
                    || userName.startsWith("yyYuY_")) {
                userName = userName.substring(userName.indexOf("_")+1);
                String[] tmp = userName.split("@");
                if(tmp !=null && tmp.length>1){
                    String[] tmp2 = tmp[1].split("\\.");
                    sb = new StringBuilder(tmp[0]);
                    sb.append("@");
                    if(tmp2!= null && tmp2.length>1){
                        for(int i=0; i< tmp2[0].length(); i ++){
                            sb.append("*");
                        }
                        for(int j=1; j < tmp2.length; j ++){
                            sb.append(".").append(tmp2[j]);
                        }
                    }
                    userName = sb.toString();
                }                
            }
        }
        return userName;
    }

    /**
     * 将一个整数字符串分解成一个整数数组 例： num=123; --> numArray[3]{1,2,3}
     *
     * @param num
     * @return
     */
    public static int[] strToIntArray(String num) {
        String[] strArray = num.trim().split("");
        int[] numArray = new int[strArray.length - 1];
        for (int i = 1; i < strArray.length; i++) {
            numArray[i - 1] = Integer.parseInt(strArray[i]);
        }
        return numArray;
    }

    /**
     * 将一个字符串分解成一个字符数组
     *
     * @param str
     * @return
     */
    public static String[] strToStrArray(String str) {
        String[] strArray = str.trim().split("");
        String[] numArray = new String[strArray.length - 1];
        for (int i = 1; i < strArray.length; i++) {
            numArray[i - 1] = strArray[i];
        }
        return numArray;
    }

    public static String subString(String str, int subBytes) {
        int bytes = 0; // 用来存储字符串的总字节数
        for (int i = 0; i < str.length(); i++) {
            if (bytes == subBytes) {
                return str.substring(0, i);
            }
            char c = str.charAt(i);
            if (c < 256) {
                bytes += 1; // 英文字符的字节数看作1
            } else {
                bytes += 2; // 中文字符的字节数看作2
                if (bytes - subBytes == 1) {
                    return str.substring(0, i);
                }
            }
        }
        return str;
    }

    public static double percentToDouble(String percent) {
        NumberFormat numberFormat = NumberFormat.getPercentInstance();

        try {
            return numberFormat.parse(percent).doubleValue();
        } catch (ParseException e) {
            return 0d;
        }
    }

    // 四舍五入

    public static int doubleToInt(double value) {
        BigDecimal bigDecimal = new BigDecimal(value).setScale(0, BigDecimal.ROUND_HALF_UP);
        return bigDecimal.intValue();
    }

    public static String getWeek(String dateStr, String style) {
        Date date = formatDate(dateStr, style);
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        int week = c.get(Calendar.DAY_OF_WEEK);
        return weekChinaMap.get(week);
    }

    public static String decompressData(String encdata) {
        try {
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            InflaterOutputStream zos = new InflaterOutputStream(bos);

            zos.write(Base64.decode(encdata.toCharArray()));
            zos.close();
            return new String(bos.toByteArray());
        } catch (Exception ex) {
            ex.printStackTrace();
            return "UNZIP_ERR";
        }
    }

    public static String compressData(String encdata) {
        try {
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            DeflaterOutputStream zos = new DeflaterOutputStream(bos);
            zos.write(encdata.getBytes());
            zos.close();
            return new String(Base64.encode(bos.toByteArray()));
        } catch (Exception ex) {
            ex.printStackTrace();
            return "ZIP_ERR";
        }
    }

    public static String getXmlBody(XmlBean xml) {
        try {
            return xml.toString().split("><!\\[CDATA\\[")[1].split("\\]\\]")[0];
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    
    public static Map convertBean(Object bean) {
        Map returnMap = new HashMap();
        try {
            Class type = bean.getClass();
            BeanInfo beanInfo = Introspector.getBeanInfo(type);

            PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
            for (int i = 0; i < propertyDescriptors.length; i++) {
                PropertyDescriptor descriptor = propertyDescriptors[i];
                String propertyName = descriptor.getName();
                if (!propertyName.equals("class")) {
                    Method readMethod = descriptor.getReadMethod();
                    Object result = readMethod.invoke(bean, new Object[0]);
                    if (result != null) {
                        returnMap.put(propertyName, result);
                    } else {
                        returnMap.put(propertyName, "");
                    }
                }
            }
        } catch (Exception e) {
            logger.error("error:" + e.getMessage());
        }
        return returnMap;
    }
    
    
    
    public static Object convertMap(Class type, Map map) {
    	Object obj = null; // 创建 JavaBean 对象
		try {
			BeanInfo beanInfo = Introspector.getBeanInfo(type);
			obj = type.newInstance(); // 创建 JavaBean 对象
			// 给 JavaBean 对象的属性赋值
			PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
			for(PropertyDescriptor descriptor : propertyDescriptors){	
				String propertyName = descriptor.getName();
				if (map.containsKey(propertyName)) {
					Object value = map.get(propertyName);
					Object[] args = new Object[1];
					args[0] = value;
					descriptor.getWriteMethod().invoke(obj, args);
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		} 
		return obj;
	}  


    public static String string2TimezoneDefault(String srcDateTime,
                                                String dstTimeZoneId) {
        return string2Timezone("yyyy-MM-dd HH:mm:ss", srcDateTime, "yyyy-MM-dd HH:mm:ss", dstTimeZoneId);
    }

    public static Date string2TimezoneDate(String srcDateTime,
                                           String dstTimeZoneId) {
        return string2Timezone("yyyy-MM-dd HH:mm:ss", srcDateTime, dstTimeZoneId);
    }

    public static String string2Timezone(String srcFormater,
                                         String srcDateTime, String dstFormater, String dstTimeZoneId) {
        if (srcFormater == null || "".equals(srcFormater))
            return null;
        if (srcDateTime == null || "".equals(srcDateTime))
            return null;
        if (dstFormater == null || "".equals(dstFormater))
            return null;
        if (dstTimeZoneId == null || "".equals(dstTimeZoneId))
            return null;
        SimpleDateFormat sdf = new SimpleDateFormat(srcFormater);
        try {
            int diffTime = getDiffTimeZoneRawOffset(dstTimeZoneId);
            Date d = sdf.parse(srcDateTime);
            long nowTime = d.getTime();
            long newNowTime = nowTime - diffTime;
            d = new Date(newNowTime);
            return Utils.formatDate2Str(d, dstFormater);
        } catch (Exception e) {
            return null;
        } finally {
            sdf = null;
        }
    }

    public static Date string2Timezone(String srcFormater,
                                       String srcDateTime, String dstTimeZoneId) {
        if (srcFormater == null || "".equals(srcFormater))
            return null;
        if (srcDateTime == null || "".equals(srcDateTime))
            return null;
        if (dstTimeZoneId == null || "".equals(dstTimeZoneId))
            return null;
        SimpleDateFormat sdf = new SimpleDateFormat(srcFormater);
        try {
            int diffTime = getDiffTimeZoneRawOffset(dstTimeZoneId);
            Date d = sdf.parse(srcDateTime);
            long nowTime = d.getTime();
            long newNowTime = nowTime - diffTime;
            d = new Date(newNowTime);
            return d;
        } catch (Exception e) {
            return null;
        } finally {
            sdf = null;
        }
    }

    private static int getDiffTimeZoneRawOffset(String timeZoneId) {
        return TimeZone.getDefault().getRawOffset()
                - TimeZone.getTimeZone(timeZoneId).getRawOffset();
    }


    /**
     * 提供精确的加法运算。
     *
     * @param v1 被加数
     * @param v2 加数
     * @return 两个参数的和
     */
    public static double add(double v1, double v2) {
        BigDecimal b1 = new BigDecimal(Double.toString(v1));
        BigDecimal b2 = new BigDecimal(Double.toString(v2));
        return b1.add(b2).doubleValue();
    }

    /**
     * 提供精确的减法运算。
     *
     * @param v1 被减数
     * @param v2 减数
     * @return 两个参数的差
     */
    public static double sub(double v1, double v2) {
        BigDecimal b1 = new BigDecimal(Double.toString(v1));
        BigDecimal b2 = new BigDecimal(Double.toString(v2));
        return b1.subtract(b2).doubleValue();
    }

    /**
     * 提供精确的乘法运算。
     *
     * @param v1 被乘数
     * @param v2 乘数
     * @return 两个参数的积
     */
    public static double mul(double v1, double v2) {
        BigDecimal b1 = new BigDecimal(Double.toString(v1));
        BigDecimal b2 = new BigDecimal(Double.toString(v2));
        return b1.multiply(b2).doubleValue();
    }

    /**
     * 提供（相对）精确的除法运算，当发生除不尽的情况时，精确到
     * 小数点以后10位，以后的数字四舍五入。
     *
     * @param v1 被除数
     * @param v2 除数
     * @return 两个参数的商
     */
    public static double div(double v1, double v2) {
        return div(v1, v2, 10);
    }

    /**
     * 提供（相对）精确的除法运算。当发生除不尽的情况时，由scale参数指
     * 定精度，以后的数字四舍五入。
     *
     * @param v1    被除数
     * @param v2    除数
     * @param scale 表示表示需要精确到小数点以后几位。
     * @return 两个参数的商
     */
    public static double div(double v1, double v2, int scale) {
        if (scale < 0) {
            throw new IllegalArgumentException("The scale must be a positive integer or zero");
        }
        BigDecimal b1 = new BigDecimal(Double.toString(v1));
        BigDecimal b2 = new BigDecimal(Double.toString(v2));
        return b1.divide(b2, scale, BigDecimal.ROUND_HALF_UP).doubleValue();
    }

    /**
     * 提供精确的小数位四舍五入处理。
     *
     * @param v     需要四舍五入的数字
     * @param scale 小数点后保留几位
     * @return 四舍五入后的结果
     */
    public static double round(double v, int scale) {
        if (scale < 0) {
            throw new IllegalArgumentException(
                    "The scale must be a positive integer or zero");
        }
        BigDecimal b = new BigDecimal(Double.toString(v));
        BigDecimal one = new BigDecimal("1");
        return b.divide(one, scale, BigDecimal.ROUND_HALF_UP).doubleValue();
    }

    public static Date string2TimeZone(String srcTime, String srcTimeZoneId) {
        return string2DefaultTimezone("yyyy-MM-dd HH:mm:ss", srcTime, srcTimeZoneId);
    }


    public static Date string2DefaultTimezone(String srcFormater,
                                              String srcDateTime, String srcTimeZoneId) {
        if (srcFormater == null || "".equals(srcFormater))
            return null;
        if (srcDateTime == null || "".equals(srcDateTime))
            return null;
        if (srcTimeZoneId == null || "".equals(srcTimeZoneId))
            return null;
        SimpleDateFormat sdf = new SimpleDateFormat(srcFormater);
        try {
            int diffTime = getDiffTimeZoneRawOffset(srcTimeZoneId);
            Date d = sdf.parse(srcDateTime);
            long nowTime = d.getTime();
            long newNowTime = nowTime + diffTime;
            d = new Date(newNowTime);
            return d;
        } catch (Exception e) {
            return null;
        } finally {
            sdf = null;
        }
    }

    public static Date converDate(String convertString, String format, String sourceTimeZoneId, String targetTimeZoneId) {
        TimeZone sourceTimeZone = TimeZone.getTimeZone(sourceTimeZoneId);
        TimeZone targetTimeZone = TimeZone.getTimeZone(targetTimeZoneId);
        SimpleDateFormat inputFormat = new SimpleDateFormat(format);
        inputFormat.setTimeZone(sourceTimeZone);
        Date date = null;
        try {
            date = inputFormat.parse(convertString);
        } catch (ParseException e) {
        }
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.setTimeZone(targetTimeZone);
        return calendar.getTime();
    }
    
    public static String gradeLV(String grade,String lotteryCode){
		String nameLV = "加油";
		String temp = "Lv";
		if(Utils.isEmpty(grade) || Utils.isEmpty(lotteryCode)){
			return nameLV;
		}
		if(ArrayUtils.contains(NUM_LOTTERY, lotteryCode)){
			int gradeInt = Integer.valueOf(grade)-20;
			if(gradeInt >= 0  && gradeInt <1000){
				int i = gradeInt/100+1;
				nameLV = "数字彩新秀"+temp+String.valueOf(i);
			}else if(gradeInt >= 1000  && gradeInt <4000){
				int i = (gradeInt-1000)/300 + 1;
				nameLV = "数字彩高手"+temp+String.valueOf(i);
			}else if(gradeInt >= 4000  && gradeInt <14000){
				int i = (gradeInt-4000)/1000 + 1;
				nameLV = "数字彩精英"+temp+String.valueOf(i);
			}else if(gradeInt >= 14000  && gradeInt <44000){
				int i = (gradeInt-14000)/3000 + 1;
				nameLV = "数字彩专家"+temp+String.valueOf(i);
			}else if(gradeInt >= 44000  && gradeInt <124000){
				int i = (gradeInt-44000)/8000 + 1;
				nameLV = "数字彩大师"+temp+String.valueOf(i);
			}else if(gradeInt >= 124000  && gradeInt <274000){
				int i = (gradeInt-124000)/15000 + 1;
				nameLV = "数字彩宗师"+temp+String.valueOf(i);
			}else if(gradeInt >= 274000  && gradeInt <574000){
				int i = (gradeInt-274000)/30000 + 1;
				nameLV = "数字彩大神"+temp+String.valueOf(i);
			}else if(gradeInt >= 574000  && gradeInt <1374000){
				int i = (gradeInt-574000)/80000 + 1;
				nameLV = "数字彩至尊"+temp+String.valueOf(i);
			}else if(gradeInt >=1374000){
				nameLV = "数字彩至尊Lv10";
			}
			
		}else if(ArrayUtils.contains(MATCH_LOTTERY, lotteryCode)){
			int gradeInt = Integer.valueOf(grade)-50;
			if(gradeInt >=0 && gradeInt < 3000){
				int j = gradeInt/300 + 1;
				nameLV = "竞彩新秀"+temp+String.valueOf(j);
			}else if(gradeInt >=3000 && gradeInt < 13000){
				int j = (gradeInt - 3000)/1000 + 1;
				nameLV = "竞彩高手"+temp+String.valueOf(j);
			}else if(gradeInt >=13000 && gradeInt < 63000){
				int j = (gradeInt - 13000)/5000 + 1;
				nameLV = "竞彩精英"+temp+String.valueOf(j);
			}else if(gradeInt >=63000 && gradeInt < 163000){
				int j = (gradeInt - 63000)/10000 + 1;
				nameLV = "竞彩专家"+temp+String.valueOf(j);
			}else if(gradeInt >=163000 && gradeInt < 663000){
				int j = (gradeInt - 163000)/50000 + 1;
				nameLV = "竞彩大师"+temp+String.valueOf(j);
			}else if(gradeInt >=663000 && gradeInt < 1663000){
				int j = (gradeInt - 163000)/100000 + 1;
				nameLV = "竞彩宗师"+temp+String.valueOf(j);
			}else if(gradeInt >=1663000 && gradeInt < 3663000){
				int j = (gradeInt - 1663000)/200000 + 1;
				nameLV = "竞彩大神"+temp+String.valueOf(j);
			}else if(gradeInt >=3663000 && gradeInt < 8663000){
				int j = (gradeInt -3663000)/500000 + 1;
				nameLV = "竞彩至尊"+temp+String.valueOf(j);
			}else if(gradeInt >= 8663000){
				nameLV = "竞彩至尊Lv10";
			}
		}
		return nameLV;
		
	}
    
    /**
	 * 动态组装消息内容
	 * @param param
	 * @param mesg
	 * @return
	 */
	public static String getBody(String [] param ,String mesg){
		
		StringBuffer buffer = new StringBuffer();
		String [] strBy = mesg.split("\\?");
		if(param.length > strBy.length) return null;
		int index = 0;
		for(int i = 0; i < param.length ; i++){
			buffer.append(strBy[i] + param[i]);
			index ++;
		}
		if(index != strBy.length){
			for(int i = index;i < strBy.length;i++){
				buffer.append(strBy[i]);
			}
		}
		return buffer.toString();
	}

	/**
	 * 验证手机号
	 * @param mobiles
	 * @return
	 */
	public static boolean isMobileNO(String mobiles) {
		Pattern p = Pattern
				.compile("^((13[0-9])|(14[5|7])|(15[^4,\\D])|(17[^1-5|^9])|(18[0-9]))\\d{8}$");

		Matcher m = p.matcher(mobiles);

		return m.matches();
	}

	/***验证身份证 begin**/
	
	public static boolean IDCardValidate(String IDStr) throws ParseException {          
        String tipInfo = "该身份证有效！";// 记录错误信息  
        boolean isCardTrue = true;
        String Ai = "";  
        // 判断号码的长度 15位或18位  
        if (IDStr.length() != 15 && IDStr.length() != 18) {  
            tipInfo = "身份证号码长度应该为15位或18位。";
            logger.info(tipInfo);
            isCardTrue = false;
            return isCardTrue;  
        }  
           
   
        // 18位身份证前17位位数字，如果是15位的身份证则所有号码都为数字  
        if (IDStr.length() == 18) {  
            Ai = IDStr.substring(0, 17);  
        } else if (IDStr.length() == 15) {  
            Ai = IDStr.substring(0, 6) + "19" + IDStr.substring(6, 15);  
        }  
        if (isNumeric(Ai) == false) {  
            tipInfo = "身份证15位号码都应为数字 ; 18位号码除最后一位外，都应为数字。";
            logger.info(tipInfo);
            isCardTrue = false;
            return isCardTrue;  
        }  
           
   
        // 判断出生年月是否有效   
        String strYear = Ai.substring(6, 10);// 年份  
        String strMonth = Ai.substring(10, 12);// 月份  
        String strDay = Ai.substring(12, 14);// 日期  
        if (isDate(strYear + "-" + strMonth + "-" + strDay) == false) {  
            tipInfo = "身份证出生日期无效。";  
            logger.info(tipInfo);
            isCardTrue = false;
            return isCardTrue;  
        }  
        GregorianCalendar gc = new GregorianCalendar();  
        SimpleDateFormat s = new SimpleDateFormat("yyyy-MM-dd");  
        try {  
            if ((gc.get(Calendar.YEAR) - Integer.parseInt(strYear)) > 150 
                    || (gc.getTime().getTime() - s.parse(  
                            strYear + "-" + strMonth + "-" + strDay).getTime()) < 0) {  
                tipInfo = "身份证生日不在有效范围。";  
                logger.info(tipInfo);
	            isCardTrue = false;
	            return isCardTrue;  
            }  
        } catch (NumberFormatException e) {  
            e.printStackTrace();  
        } catch (java.text.ParseException e) {  
            e.printStackTrace();  
        }  
        if (Integer.parseInt(strMonth) > 12 || Integer.parseInt(strMonth) == 0) {  
            tipInfo = "身份证月份无效";  
            logger.info(tipInfo);
            isCardTrue = false;
            return isCardTrue;  
        }  
        if (Integer.parseInt(strDay) > 31 || Integer.parseInt(strDay) == 0) {  
            tipInfo = "身份证日期无效";  
            logger.info(tipInfo);
            isCardTrue = false;
            return isCardTrue;   
        }  
           
   
        // 判断地区码是否有效   
        Hashtable areacode = GetAreaCode();  
        //如果身份证前两位的地区码不在Hashtable，则地区码有误  
        if (areacode.get(Ai.substring(0, 2)) == null) {  
            tipInfo = "身份证地区编码错误。";  
            logger.info(tipInfo);
            isCardTrue = false;
            return isCardTrue;  
        }  
           
        if(isVarifyCode(Ai,IDStr)==false){  
            tipInfo = "身份证校验码无效，不是合法的身份证号码";  
            logger.info(tipInfo);
            isCardTrue = false;
            return isCardTrue;    
        }  
          
           
        return isCardTrue; 
    }  
       
       
     /* 
      * 判断第18位校验码是否正确 
     * 第18位校验码的计算方式：  
        　　1. 对前17位数字本体码加权求和  
        　　公式为：S = Sum(Ai * Wi), i = 0, ... , 16  
        　　其中Ai表示第i个位置上的身份证号码数字值，Wi表示第i位置上的加权因子，其各位对应的值依次为： 7 9 10 5 8 4 2 1 6 3 7 9 10 5 8 4 2  
        　　2. 用11对计算结果取模  
        　　Y = mod(S, 11)  
        　　3. 根据模的值得到对应的校验码  
        　　对应关系为：  
        　　 Y值：     0  1  2  3  4  5  6  7  8  9  10  
        　　校验码： 1  0  X  9  8  7  6  5  4  3   2 
     */  
    private static boolean isVarifyCode(String Ai,String IDStr) {  
         String[] VarifyCode = { "1", "0", "X", "9", "8", "7", "6", "5", "4","3", "2" };  
         String[] Wi = { "7", "9", "10", "5", "8", "4", "2", "1", "6", "3", "7","9", "10", "5", "8", "4", "2" };  
         int sum = 0;  
         for (int i = 0; i < 17; i++) {  
            sum = sum + Integer.parseInt(String.valueOf(Ai.charAt(i))) * Integer.parseInt(Wi[i]);  
         }  
         int modValue = sum % 11;  
         String strVerifyCode = VarifyCode[modValue];  
         Ai = Ai + strVerifyCode;  
         if (IDStr.length() == 18) {  
             if (Ai.equals(IDStr) == false) {  
                 return false;  
                   
             }  
         }   
         return true;  
    }  
       
   
    /** 
     * 将所有地址编码保存在一个Hashtable中     
     * @return Hashtable 对象 
     */  
      
    private static Hashtable GetAreaCode() {  
        Hashtable hashtable = new Hashtable();  
        hashtable.put("11", "北京");  
        hashtable.put("12", "天津");  
        hashtable.put("13", "河北");  
        hashtable.put("14", "山西");  
        hashtable.put("15", "内蒙古");  
        hashtable.put("21", "辽宁");  
        hashtable.put("22", "吉林");  
        hashtable.put("23", "黑龙江");  
        hashtable.put("31", "上海");  
        hashtable.put("32", "江苏");  
        hashtable.put("33", "浙江");  
        hashtable.put("34", "安徽");  
        hashtable.put("35", "福建");  
        hashtable.put("36", "江西");  
        hashtable.put("37", "山东");  
        hashtable.put("41", "河南");  
        hashtable.put("42", "湖北");  
        hashtable.put("43", "湖南");  
        hashtable.put("44", "广东");  
        hashtable.put("45", "广西");  
        hashtable.put("46", "海南");  
        hashtable.put("50", "重庆");  
        hashtable.put("51", "四川");  
        hashtable.put("52", "贵州");  
        hashtable.put("53", "云南");  
        hashtable.put("54", "西藏");  
        hashtable.put("61", "陕西");  
        hashtable.put("62", "甘肃");  
        hashtable.put("63", "青海");  
        hashtable.put("64", "宁夏");  
        hashtable.put("65", "新疆");  
        hashtable.put("71", "台湾");  
        hashtable.put("81", "香港");  
        hashtable.put("82", "澳门");  
        hashtable.put("91", "国外");  
        return hashtable;  
    }  
   
    /** 
     * 判断字符串是否为数字,0-9重复0次或者多次    
     * @param strnum 
     * @return 
     */  
    private static boolean isNumeric(String strnum) {  
        Pattern pattern = Pattern.compile("[0-9]*");  
        Matcher isNum = pattern.matcher(strnum);  
        if (isNum.matches()) {  
            return true;  
        } else {  
            return false;  
        }  
    }  
   
    /** 
     * 功能：判断字符串出生日期是否符合正则表达式：包括年月日，闰年、平年和每月31天、30天和闰月的28天或者29天 
     *  
     * @param string 
     * @return 
     */ 
    public static boolean isDate(String strDate) {  
       
        Pattern pattern = Pattern  
                .compile("^((\\d{2}(([02468][048])|([13579][26]))[\\-\\/\\s]?((((0?[13578])|(1[02]))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(3[01])))|(((0?[469])|(11))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(30)))|(0?2[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])))))|(\\d{2}(([02468][1235679])|([13579][01345789]))[\\-\\/\\s]?((((0?[13578])|(1[02]))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(3[01])))|(((0?[469])|(11))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(30)))|(0?2[\\-\\/\\s]?((0?[1-9])|(1[0-9])|(2[0-8]))))))?$");  
        Matcher m = pattern.matcher(strDate);  
        if (m.matches()) {  
            return true;  
        } else {  
            return false;  
        }  
    }  
    
    /***
     * 判断字段真实长度（中文2个字符，英文1个字符）
     * @param value
     * @return
     */
	public static int StringLength(String value) {
		int valueLength = 0;
		String chinese = "[\u4e00-\u9fa5]";
		for (int i = 0; i < value.length(); i++) {
			String temp = value.substring(i, i + 1);
			if (temp.matches(chinese)) {
				valueLength += 2;
			} else {
				valueLength += 1;
			}
		}
		return valueLength;
	}
	/**
	 * 验证昵称，是否为数字、字母、汉字、下划线组合
	 * @param nickName
	 * @return
	 */
	public static boolean isNickName(String nickName) {
		Pattern p = Pattern.compile("^((\\w)|([\\u4e00-\\u9fa5]))*$");

		Matcher m = p.matcher(nickName);

		return m.matches();
	}

	
	/***验证身份证end**/
	public static void main(String[] args) {
		System.out.println(!isMobileNO("13520255580"));
		;
		Date nDate = Utils.formatDate("2015-04-30 11:00:00");  // 当前时间
		System.out.println(Utils.formatDate2Str(nDate, null));
		Date bDate = Utils.addDate(nDate, "mi", 30);
		System.out.println(Utils.formatDate2Str(bDate, null));
		Date aDate = Utils.addDate(nDate, "mi", -31);
		System.out.println(Utils.formatDate2Str(aDate, null));
		System.out.println(isNickName("asdajka_1"));
		System.out.println(isNickName("啊1"));
		System.out.println(!(Utils.StringLength("啊1") > 3));
	}
}
